__author__ = 'DanMan'
from random import randint
from time import clock

##=======================================
State = type("State", (object,), {})


class LighOn(State):
    def Execute(self):
        print("LighOn")


class LightOff(State):
    def Execute(self):
        print("LightOff")


##=======================================

class Transition(object):
    def __init__(self, toState):
        self.toState = toState

    def Execute(self):
        print("Transitioning...")


##======================================

class SimpleFSM(object):
    def __init__(self, char):
        self.char = char
        self.states = {}
        self.transitions = {}
        self.curState = None
        self.curTrans = None

    def SetState(self, stateName):
        self.curState = self.states[stateName]

    def Transition(self, transName):
        self.curTrans = self.transitions[transName]

    def Execute(self):
        if self.curTrans:
            self.curTrans.Execute()
            self.SetState(self.curTrans.toState)
            self.curTrans = None
        self.curState.Execute(self)
##=====================================

class Char(object):
    def __init__(self):
        self.FSM = SimpleFSM(self)
        self.LightOn = True

##=====================================

if __name__ == '__main__':
    light = Char()

    light.FSM.states["ON"] = LighOn
    light.FSM.states["OFF"] = LightOff
    light.FSM.transitions["toON"] = Transition("ON")
    light.FSM.transitions["toOFF"] = Transition("OFF")

    light.FSM.SetState("ON")

    for i in range(20):
        startTime = clock()
        timeInterval = 1
        while (startTime + timeInterval > clock()):
            pass
        if (randint(0,2)):
            if (light.LightOn):
                light.FSM.Transition("toOFF")
                light.LightOn = False
            else:
                light.FSM.Transition("toON")
                light.LightOn = True
        light.FSM.Execute()
